package com.auto.survey.activity.monitoring.dao

import android.util.Log
import com.auto.survey.activity.monitoring.entity.MonitorCheckPoint
import com.auto.survey.activity.monitoring.entity.MonitoringObject
import com.auto.survey.activity.monitoring.entity.MonitoringObservation
import com.auto.survey.activity.monitoring.entity.MonitoringPoint
import com.auto.survey.activity.monitoring.entity.MonitoringPointCtrlObservation
import com.auto.survey.activity.monitoring.entity.MonitoringStation
import com.auto.survey.activity.monitoring.entity.MontoringProject
import com.auto.survey.activity.monitoring.entity.Point
import com.auto.survey.activity.monitoring.entity.ctrlmeasure.ClosedLoopObservation
import com.auto.survey.activity.monitoring.entity.ctrlmeasure.ClosedLoopWithPoints
import com.auto.survey.activity.monitoring.entity.ctrlmeasure.LoopObservationPoint
import com.auto.survey.activity.monitoring.entity.ctrlmeasure.StationWithClosedLoop
import com.auto.survey.activity.monitoring.entity.relations.MonitoringPointWithCtrlObserv
import com.auto.survey.activity.monitoring.entity.relations.MonitoringPointWithObservations
import com.auto.survey.activity.monitoring.entity.relations.PointWithCheckedPoint
import com.auto.survey.base.CustomApplication
import com.auto.survey.database.AppDatabase
import com.auto.survey.util.monitoring.entity.CalculationResultWithDetailsTemp
import com.auto.survey.util.monitoring.entity.RearIntersectionCalculationResultWithDetails
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext

class MonitoringRepository {

    companion object{
        val TAG:String = MonitoringRepository::class.java.simpleName
    }
    private val db: AppDatabase = AppDatabase.getInstance(CustomApplication.getContext())
    val monitoringProjectDao = db.monitoringProjectDao()

    val pointDao = db.pointDao()
    val monitoringObjectDao = db.monitoringObjectDao()
    val monitoringStationDao = db.monitoringStationDao()
    val monitoringPointDao = db.monitoringPointDao()
    val monitoringWithCheckPointDao = db.monitoringWithCheckPointDao()
    val monitoringCheckPointDao = db.monitoringCheckPointDao()

    val calculationResultDao = db.calculationDao()

    val calculationStationDao = db.calculationStationDao()

    val nocompliantPoinDao = db.nonCompliantPointDao()

    val verificationDao = db.verificationResultDao()

    val moitoringPointCtrlObservDao = db.moitoringPointCtrlObservDao()

    val monitoringPointWithCtrlObservDao = db.monitoringPointWithCtrlObservDao()

    val closedLoopObservationDao = db.closedLoopObservationDao()

    val loopObservationPointDao = db.loopObservationPointDao()

    val monitoringPointCtrlObservationDao = db.monitoringPointWithCtrlObservDao()

    /**
     * 创建项目
     */
    suspend fun createProject(project: MontoringProject):Long{

        return monitoringProjectDao.insertMontoringProject(project)
    }

    /**
     * 获取项目列表
     */
    suspend fun getProjectList(): Flow<List<MontoringProject>> {
        return monitoringProjectDao.getMonitoringProjects()
    }

    suspend fun getProjectById(id:Int):MontoringProject? {
        return monitoringProjectDao.getMontoringProjectById(id)
    }

    /**
     * 删除项目
     */
    suspend fun deleteProjectById(id:Int){
        monitoringProjectDao.deleteMontoringProjectById(id)
    }

    /**
     * 编辑项目
     */
    suspend fun updateProject(project: MontoringProject){
        monitoringProjectDao.updateMontoringProject(project)
    }

    /**
     * 根据项目ID获取对应的监测对象列表
     */
    suspend fun getObjectsByProjectId(projectId:Int): Flow<List<MonitoringObject>>{
        return monitoringObjectDao.getMonitoringObjectByProjectId(projectId)
    }

    suspend fun createObject(monitoring: MonitoringObject): Long{
        return  monitoringObjectDao.insertMonitoringObject(monitoring)
    }

    suspend fun getPointsByObjId(objId: Int) :Flow<List<Point>>{
        return pointDao.getPointsByObjectId(objId)
    }

    suspend fun createPoint(point: Point): Long{
        return pointDao.insertPoint(point)
    }

    suspend fun getMonitoringPointByObjectId(objectId:Int):Flow<List<MonitoringPoint>>{
        return  monitoringPointDao.getMonitoringPointsByObjectId(objectId)
    }

    suspend fun getPointByObjectIdAndPtype(objectId:Int, pType:String):Flow<List<Point>>{
        return  pointDao.getPointsByObjectIdAndType(objectId, pType)
    }

    suspend fun getMonitoringPointById(pointId:Int):MonitoringPoint?{
        return monitoringPointDao.getMonitoringPointById(pointId)
    }

    suspend fun createMonitoringPoint(point: MonitoringPoint):Long{
        return monitoringPointDao.insertMonitoringPoint(point)
    }

    suspend fun getMonitoringPointSerilNum(objectId:Int):Int? {
        return monitoringPointDao.getMaxMeasurementOrder(objectId)
    }

    suspend fun getMonitoringPointClloectedByObjectId(objectId:Int):Flow<List<MonitoringPoint>> {
        return monitoringPointDao.getMonitoringPointsCollectedByObjectId(objectId)
    }

    suspend fun getMonitoringPointClloectedByStationId(stationId: Int):Flow<List<MonitoringPoint>>{
        return monitoringPointDao.getCollectedPointsByStationId(stationId)
    }


    suspend fun getCollectedPointsWithCheckedPointsByStationId(stationId:Int):Flow<List<PointWithCheckedPoint>> {
        return monitoringWithCheckPointDao.getCollectedPointsWithCheckedPointsByStationId(stationId)
    }

    suspend fun getPointClloectedCountByObjectId(objectId:Int):Int {
        return monitoringPointDao.getPointClloectedCountByObjectId(objectId)
    }

    suspend fun getPointClloectedCountByStationId(stationId:Int):Int {
        return monitoringPointDao.getPointClloectedCountByStationId(stationId)
    }



    suspend fun createStation(station: MonitoringStation):Long {
        return monitoringStationDao.insertMonitoringStation(station)
    }

    suspend fun getStationByObjectId(objectId:Int):Flow<List<MonitoringStation>>{
        return monitoringStationDao.getStationsByObjectId(objectId)
    }

    suspend fun getStationById(id:Int): MonitoringStation?{
        return monitoringStationDao.getMonitoringStationById(id)
    }

    suspend fun updateStation(station:MonitoringStation) {
        monitoringStationDao.updateMonitoringStation(station)
    }

    suspend fun updatePoint(point:MonitoringPoint) {
        monitoringPointDao.updateMonitoringPoint(point)
    }

    suspend fun createCheckPoint(checkPoint: MonitorCheckPoint):Long {
        return monitoringCheckPointDao.insert(checkPoint)
    }

    suspend fun getFirstCheckPoint(pointId:Int):MonitorCheckPoint?{
        return monitoringCheckPointDao.getByPointId(pointId).firstOrNull()
    }

    suspend fun updateCheckPoint(checkPoint: MonitorCheckPoint) {
        monitoringCheckPointDao.update(checkPoint)
    }

    suspend fun getPointWithCheckedPoints(pointId: Int):PointWithCheckedPoint?{
        return monitoringWithCheckPointDao.getPointWithCheckedPoints(pointId)
    }

    /**
     * 根据pointId查询关联的Observ
     */
    suspend fun getObservByPointId(pointId: Int): MonitoringPointWithObservations? {
        return monitoringPointDao.getMonitoringPointWithObservations(pointId)
    }

    /**
     * 基于pointId建立观测数据
     */
    suspend fun createObserv(observ:MonitoringObservation):Long {
        return monitoringPointDao.insertObserv(observ)
    }

    suspend fun saveCalculationResult(station:MonitoringStation, tempResult: CalculationResultWithDetailsTemp): Boolean {
        return try {
            // 使用事务确保数据一致性
            withContext(Dispatchers.IO) {

                val stationId = createStation(station)

                tempResult.result.stationId = stationId.toInt()

                val generatedId = calculationStationDao.insert(tempResult.result)

                val updatedVerificationResults = tempResult.verificationResults.map {
                    it.copy(calculationResultId = generatedId.toInt())
                }

                val updatedNonCompliantPoints = tempResult.nonCompliantPoints.map {
                    it.copy(calculationResultId = generatedId.toInt())
                }

                verificationDao.insertAll(updatedVerificationResults)
                nocompliantPoinDao.insertAll(updatedNonCompliantPoints)
            }
            true // 所有操作成功完成
        } catch (e: Exception) {
            Log.e("DB", "保存计算结果失败: ${e.message}", e)
            false // 发生异常，保存失败
        }
    }

    suspend fun getCalculationStationResult(stationId: Int):List<RearIntersectionCalculationResultWithDetails> {
        return  calculationResultDao.getResultsByStationId(stationId)
    }

    suspend fun getPointsWithObservationsByStationId(stationId:Int):List<MonitoringPointWithCtrlObserv>{
        return monitoringPointWithCtrlObservDao.getPointsWithObservationsByStationId(stationId)
    }

    suspend fun getStationWithClosedLoops(stationId: Int): StationWithClosedLoop?{
        return monitoringStationDao.getStationWithClosedLoops(stationId)
    }

    suspend fun addCtrlTask(task: ClosedLoopObservation): Long{
        return closedLoopObservationDao.insert(task)
    }

    suspend fun getTaskPointList(taskId: Int): ClosedLoopWithPoints?{
        return closedLoopObservationDao.getClosedLoopWithPointsById(taskId)
    }

    suspend fun addTaskPoints(points: List<LoopObservationPoint>) {
        loopObservationPointDao.insertAll(points)
    }

    suspend fun updateTask(task: ClosedLoopObservation) {
        closedLoopObservationDao.update(task)
    }

    suspend fun addMonitoringPointCtrlObservation(observations: List<MonitoringPointCtrlObservation>): List<Long> {
        return moitoringPointCtrlObservDao.insertObservations(observations)
    }

    suspend fun getMonitoringPointCtrlObservationByPid(pointId: Int): MonitoringPointWithCtrlObserv?{
        return monitoringPointCtrlObservationDao.getPointWithObservations(pointId)
    }

}